<?php
class channel extends basic { //todo:  implements remote_export
	const	none = 0,
			nethack = 1,
			forbidden = 2,
			suspended = 4,
			restricted = 8,
			netsplit = 16;
	public	$users = array(),
			$modes = null,
			$created = 0,
			$topic_is = '',
			$topic_by = '',
			$topic_at = 0,
			$tag = self::none;
	public function construct(array $pars = null) {
		extract($pars, EXTR_REFS);
		if (!isset($created) or !is_int($created) or $created < 0)
			throw new exception_channel_badcreated("Invalid \$created parameter for $this->name");
		if (array_key_exists($this->name,$GLOBALS['channels']))
			throw new exception_channel_doublereg("failed to register channel $this->name; the name already exists in global channel list");
		$this->modes = new modes_channel($this);
		$this->created = ($created ? $created : time());
		$GLOBALS['channels'][$this->tolower()] =& $this;
	}
	public function destruct() {
		if (!array_key_exists($this->tolower(),$GLOBALS['channels']))
			return false;
		try {
			callback_module::run('channel_destruct',array(&$this,$reason));
		} catch (Exception $ex) {
			if ($ex instanceof exception_channel_abortdestruct)
				return $ex->getMessage();
			else
				throw $ex;
		}
		unset($GLOBALS['basics'][$this->oid()]);
		unset($GLOBALS['channels'][$this->tolower()]);
		$warn_ghosts = array();
		foreach ($this->users as &$u) {
			if (!is_object($u)) continue;
			$warn_ghosts[] = $u->nick;
			unset($u->channels[$this->oid()]);
		}
		if (!empty($warn_ghosts)) {
			throw new exception_channel_ghosts("Ghosts in channel ".$this->name.": ".implode(',',$warn_ghosts));
		}
		return true;
	}
	public function valid_name($name) {
		return preg_match('/#[a-z0-9\.\_]/i',$name);
		//TODO improve
	}
	public function join (user &$u, $cumodes = '') {
		$this->users[$u->oid()] =& $u;
		$u->channels[$this->oid()] =& $this;
		if ($cumodes) {
			modes_apply($this->modes, $cumodes." ".str_repeat("{$u->name} ", strlen($cumodes)));
		}
		callback_module::run('channel_join',array(&$this,&$u,$cumodes));
		return true;
	}
	public function user_signoff(user &$u) {
		if (!array_key_exists($u->oid(),$this->users))
			return false;
		unset($this->users[$u->oid()]);
		unset($u->channels[$this->oid()]);
		if (empty($this->users)) {
			$this->destruct();
		}
		return true;
	}
	public function part (user &$u, $reason = '') {
		try {
			callback_module::run('channel_part',array(&$this,&$u,$reason));
		} catch (Exception $ex) {
			return $ex->getMessage();
		}
		return $this->user_signoff($u);
	}
	public function quit (user &$u, $reason = '') {
		try {
			callback_module::run('channel_quit',array(&$this,&$u,$reason));
		} catch (Exception $ex) {
			return $ex->getMessage();
		}
		return $this->user_signoff($u);
	}
	public function kick (user &$target, user &$source, $reason = '') {
		try {
			callback_module::run('channel_kick',array(&$this,&$source,&$target,$reason));
		} catch (Exception $ex) {
			return $ex->getMessage();
		}
		return $this->user_signoff($target);
	}
	public function topic ($topic_is, $topic_by, $topic_at = 0) {
		if (!is_string($topic_is) or !is_string($topic_by))
			throw new Exception("Invalid parameters for channel topic of $this->name",007);
		try {
			callback_module::run('channel_topic',array(&$this,$topic_is,$topic_by,$topic_at));
		} catch (Exception $ex) {
			return $ex->getMessage();
		}
		$this->topic_at = ((int)$topic_at ? (int)$topic_at : time());
		$this->topic_is = $topic_is;
		$this->topic_by = $topic_by;
		return true;
	}
	public function mode (basic &$source, $apply) {
		try {
			callback_module::run('channel_mode',array(&$this,&$source,$apply));
		} catch (Exception $ex) {
			return $ex->getMessage();
		}
		modes_apply($this->modes, $apply);
	}
}
?>
